package toolkit;
import java.io.*;
import java.util.function.Function;


/**
 * <ul>
 * <li>Title: SerializedLambda</li>
 * <li>Description: TODO </li>
 * </ul>
 *
 * @author 程序员ken
 * @date 2021/4/30 0030 上午 9:36
 */
public class SerializedLambda implements Serializable {
    private static final long serialVersionUID = 8025925345765570181L;
    private Class<?> capturingClass;
    private String functionalInterfaceClass;
    private String functionalInterfaceMethodName;
    private String functionalInterfaceMethodSignature;
    private String implClass;
    private String implMethodName;
    private String implMethodSignature;
    private int implMethodKind;
    private String instantiatedMethodType;
    private Object[] capturedArgs;

    public SerializedLambda() {
    }

    /**
     * 通过反序列化转换 lambda 表达式，该方法只能序列化 lambda 表达式，不能序列化接口实现或者正常非 lambda 写法的对象
     * @param lambda lambda对象
     * @return 返回解析后的 SerializedLambda
     */
    public static <T extends Function> SerializedLambda resolve(T lambda) {
        if (!lambda.getClass().isSynthetic()) {
            throw new RuntimeException(String.format("该方法仅能传入 lambda 表达式产生的合成类",  new Object[0]));
        } else {
            try {
                ObjectInputStream objIn = new ObjectInputStream(new ByteArrayInputStream(SerializationUtils.serialize(lambda))) {
                    protected Class<?> resolveClass(ObjectStreamClass objectStreamClass) throws IOException, ClassNotFoundException {
                        Class clazz;
                        try {
                            clazz = toClassConfident(objectStreamClass.getName());
                        } catch (Exception var4) {
                            clazz = super.resolveClass(objectStreamClass);
                        }

                        return clazz == java.lang.invoke.SerializedLambda.class ? SerializedLambda.class : clazz;
                    }
                };
                Throwable var2 = null;

                SerializedLambda var3;
                try {
                    var3 = (SerializedLambda)objIn.readObject();
                } catch (Throwable var13) {
                    var2 = var13;
                    throw var13;
                } finally {
                    if (objIn != null) {
                        if (var2 != null) {
                            try {
                                objIn.close();
                            } catch (Throwable var12) {
                                var2.addSuppressed(var12);
                            }
                        } else {
                            objIn.close();
                        }
                    }

                }

                return var3;
            } catch (IOException | ClassNotFoundException var15) {
                throw new RuntimeException(String.format("This is impossible to happen",var15, new Object[0]));
            }
        }
    }


    /**
     * 获取接口 class
     *
     * @return 返回 class 名称
     */
    public String getFunctionalInterfaceClassName() {
        return this.normalizedName(this.functionalInterfaceClass);
    }

    /**
     * 获取实现的 class
     *
     * @return 实现类
     */
    public Class<?> getImplClass() {
        return toClassConfident(this.getImplClassName());
    }

    /**
     * 获取 class 的名称
     *
     * @return 类名
     */
    public String getImplClassName() {
        return this.normalizedName(this.implClass);
    }

    /**
     * 获取实现者的方法名称
     *
     * @return 方法名称
     */
    public String getImplMethodName() {
        return this.implMethodName;
    }

    /**
     * 正常化类名称，将类名称中的 / 替换为 .
     *
     * @param name 名称
     * @return 正常的类名
     */
    private String normalizedName(String name) {
        return name.replace('/', '.');
    }

    /**
     * @return 获取实例化方法的类型
     */
    public Class<?> getInstantiatedType() {
        String instantiatedTypeName = this.normalizedName(this.instantiatedMethodType.substring(2, this.instantiatedMethodType.indexOf(59)));
        return toClassConfident(instantiatedTypeName);
    }

    /**
     * @return 字符串形式
     */
    public String toString() {
        String interfaceName = this.getFunctionalInterfaceClassName();
        String implName = this.getImplClassName();
        return String.format("%s -> %s::%s", interfaceName.substring(interfaceName.lastIndexOf(46) + 1), implName.substring(implName.lastIndexOf(46) + 1), this.implMethodName);
    }

    /**
     * <p>
     * 请仅在确定类存在的情况下调用该方法
     * </p>
     * @param name 类名称
     * @return 返回转换后的 Class
     */
    public static Class<?> toClassConfident(String name) {
        try {
            return Class.forName(name, false, getDefaultClassLoader());
        } catch (ClassNotFoundException var4) {
            try {
                return Class.forName(name);
            } catch (ClassNotFoundException var3) {
                throw new RuntimeException(String.format("找不到指定的class！请仅在明确确定会有 class 的时候，调用该方法", var4, new Object[0]));
            }
        }
    }


    /**
     *返回要使用的默认类加载器：通常是线程上下文
     *ClassLoader（如果可用）；加载ClassUtils的ClassLoader类将用作回退。
     *<p>如果要使用线程上下文类加载器，请调用此方法
     *在您显然更喜欢非空类加载器引用的场景中：
     *例如，对于类路径资源加载（但不一定是
     *{@code Class.forName}，它接受{@code null}类加载器
     *参考）。
     *@返回默认的类加载器（如果系统
     *类加载器不可访问）
     *@see线程#getContextClassLoader（）
     *@see ClassLoader#getSystemClassLoader（）
     *@自3.3.2
     */
    public static ClassLoader getDefaultClassLoader() {
        ClassLoader cl = null;

        try {
            cl = Thread.currentThread().getContextClassLoader();
        } catch (Throwable var3) {
            ;
        }

        if (cl == null) {
            cl = SerializedLambda.class.getClassLoader();
            if (cl == null) {
                try {
                    cl = ClassLoader.getSystemClassLoader();
                } catch (Throwable var2) {
                    ;
                }
            }
        }
        return cl;
    }

}
